#include "stm32regbit.h"
#include "stm32_gpio.h"

/**
 * @description: 
 * @param {u32} NVIC_VectTab
 * @param {u32} Offset
 * @return {*}
 */
void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)
{
  SCB->VTOR = NVIC_VectTab | (Offset & (u32)0xFFFFFE00); //设置NVIC的向量表偏移寄存器,VTOR低9位保留,即[8:0]保留。
}

/**
 * @description: 
 * @param {u8} NVIC_Group
 * @return {*}
 */
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)
{
  u32 temp, temp1;
  temp1 = (~NVIC_Group) & 0x07; //取后三位
  temp1 <<= 8;
  temp = SCB->AIRCR;  //读取先前的设置
  temp &= 0X0000F8FF; //清空先前分组
  temp |= 0X05FA0000; //写入钥匙
  temp |= temp1;
  SCB->AIRCR = temp; //设置分组
}

/**
 * @description: 
 * @param {u8} NVIC_PreemptionPriority
 * @param {u8} NVIC_SubPriority
 * @param {u8} NVIC_Channel
 * @param {u8} NVIC_Group
 * @return {*}
 */
void MY_NVIC_Init(u8 NVIC_PreemptionPriority, u8 NVIC_SubPriority, u8 NVIC_Channel, u8 NVIC_Group)
{
  u32 temp;
  MY_NVIC_PriorityGroupConfig(NVIC_Group); //设置分组
  temp = NVIC_PreemptionPriority << (4 - NVIC_Group);
  temp |= NVIC_SubPriority & (0x0f >> NVIC_Group);
  temp &= 0xf;                                             //取低四位
  NVIC->ISER[NVIC_Channel / 32] |= 1 << NVIC_Channel % 32; //使能中断位(要清除的话,设置ICER对应位为1即可)
  NVIC->IP[NVIC_Channel] |= temp << 4;                     //设置响应优先级和抢断优先级
}

/**
 * @description: 
 * @param {GPIO_TypeDef} *GPIOx
 * @return {*}
 */
void GPIO_EnablePort(GPIO_TypeDef *GPIOx)
{
  u32 tmpreg;
  if (GPIOx == GPIOA)
  {
    SET_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOASMEN_Msk);
    tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOASMEN_Msk);
  }
  else if (GPIOx == GPIOB)
  {
    SET_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOBSMEN_Msk);
    tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOBSMEN_Msk);
  }
  else if (GPIOx == GPIOC)
  {
    SET_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOCSMEN_Msk);
    tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOCSMEN_Msk);
  }
  else if (GPIOx == GPIOD)
  {
    SET_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIODSMEN_Msk);
    tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOCSMEN_Msk);
  }
  else if (GPIOx == GPIOE)
  {
    SET_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOESMEN_Msk);
    tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOCSMEN_Msk);
  }
  (void)(tmpreg);
}

/**
 * @description: 
 * @param {GPIO_TypeDef} *GPIOx
 * @param {uint32_t} pin
 * @param {uint32_t} mode
 * @param {uint32_t} otype
 * @param {uint32_t} speed
 * @param {uint32_t} pupd
 * @return {*}
 */
void GPIO_Config(GPIO_TypeDef *GPIOx, uint32_t pin, uint32_t mode, uint32_t otype, uint32_t speed, uint32_t pupd)
{
  uint32_t pin_pos = 0;
  pin_pos |= (1 << pin);
  //设置时钟
  /* Delay after an RCC peripheral clock enabling */
  GPIO_EnablePort(GPIOx);
  /* Initialize  pinpos on first pin set */
  //设置模式
  GPIOx->MODER &= ~(3 << pin * 2U);
  GPIOx->MODER |= (mode << pin * 2U);
  //设置速度
  if (mode == GPIO_MODE_OUTPUT || mode == GPIO_MODE_ALTERNATE)
  {
    GPIOx->OSPEEDR &= ~(3 << pin * 2U);
    GPIOx->OSPEEDR |= (speed << pin * 2U);
  }
  //设置上下拉
  GPIOx->PUPDR &= ~(3 << pin * 2U);
  GPIOx->PUPDR |= (pupd << pin * 2U);
  //设置输出模式
  if (mode == GPIO_MODE_OUTPUT || mode == GPIO_MODE_ALTERNATE)
  {
    MODIFY_REG(GPIOx->OTYPER, pin_pos, (pin_pos * otype));
  }
}

/**
 * @description: 
 * @param {GPIO_TypeDef} *GPIOx
 * @param {u8} BITx
 * @param {u8} AFx
 * @return {*}
 */
void GPIO_AF_Set(GPIO_TypeDef *GPIOx, u8 BITx, u8 AFx)
{
  GPIOx->AFR[BITx >> 3] &= ~(0X0F << ((BITx & 0X07) * 4));
  GPIOx->AFR[BITx >> 3] |= (u32)AFx << ((BITx & 0X07) * 4);
}

//
void GPIO_Set(GPIO_TypeDef *GPIOx, uint32_t pin, u8 status)
{
  if (status)
  {
    WRITE_REG(GPIOx->BSRR, 1 << pin);
  }

  else
  {
    WRITE_REG(GPIOx->BRR, 1 << pin);
  }
}